import requests
import json
from typing import Dict, Optional, Any

class HttpClient:
    """通用HTTP请求客户端类，封装常用的HTTP方法"""
    
    def __init__(self, base_url: str = "", timeout: int = 10, headers: Optional[Dict[str, str]] = None):
        """
        初始化HTTP客户端
        
        :param base_url: 基础URL，所有请求的URL会基于此拼接
        :param timeout: 请求超时时间，默认10秒
        :param headers: 默认请求头
        """
        self.base_url = base_url
        self.timeout = timeout
        self.headers = headers or {}
        # 默认添加JSON Content-Type
        if "Content-Type" not in self.headers:
            self.headers["Content-Type"] = "application/json"
    
    def get(self, url: str, params: Optional[Dict[str, Any]] = None, headers: Optional[Dict[str, str]] = None) -> Dict[str, Any]:
        """
        发送GET请求
        
        :param url: 请求URL，若base_url已设置，则可传入相对路径
        :param params: 查询参数
        :param headers: 额外请求头，会覆盖默认请求头
        :return: 响应JSON数据
        :raises requests.exceptions.RequestException: 请求异常时抛出
        """
        return self._request("GET", url, params=params, headers=headers)
    
    def post(self, url: str, data: Optional[Dict[str, Any]] = None, json: Optional[Dict[str, Any]] = None, headers: Optional[Dict[str, str]] = None) -> Dict[str, Any]:
        """
        发送POST请求
        
        :param url: 请求URL，若base_url已设置，则可传入相对路径
        :param data: 表单数据
        :param json: JSON数据
        :param headers: 额外请求头，会覆盖默认请求头
        :return: 响应JSON数据
        :raises requests.exceptions.RequestException: 请求异常时抛出
        """
        return self._request("POST", url, data=data, json=json, headers=headers)
    
    def put(self, url: str, data: Optional[Dict[str, Any]] = None, json: Optional[Dict[str, Any]] = None, headers: Optional[Dict[str, str]] = None) -> Dict[str, Any]:
        """
        发送PUT请求
        
        :param url: 请求URL，若base_url已设置，则可传入相对路径
        :param data: 表单数据
        :param json: JSON数据
        :param headers: 额外请求头，会覆盖默认请求头
        :return: 响应JSON数据
        :raises requests.exceptions.RequestException: 请求异常时抛出
        """
        return self._request("PUT", url, data=data, json=json, headers=headers)
    
    def delete(self, url: str, headers: Optional[Dict[str, str]] = None) -> Dict[str, Any]:
        """
        发送DELETE请求
        
        :param url: 请求URL，若base_url已设置，则可传入相对路径
        :param headers: 额外请求头，会覆盖默认请求头
        :return: 响应JSON数据
        :raises requests.exceptions.RequestException: 请求异常时抛出
        """
        return self._request("DELETE", url, headers=headers)
    
    def _request(self, method: str, url: str, **kwargs) -> Dict[str, Any]:
        """
        内部请求方法，处理所有HTTP请求
        
        :param method: HTTP方法
        :param url: 请求URL
        :param kwargs: 其他请求参数
        :return: 响应JSON数据
        """
        # 拼接完整URL
        full_url = f"{self.base_url}{url}" if self.base_url else url
        
        # 合并请求头
        request_headers = self.headers.copy()
        if kwargs.get("headers"):
            request_headers.update(kwargs.pop("headers"))
        
        # 发送请求
        response = requests.request(
            method=method,
            url=full_url,
            timeout=self.timeout,
            headers=request_headers,
            **kwargs
        )
        
        # 检查响应状态码
        response.raise_for_status()
        
        # 解析JSON响应
        try:
            return response.json()
        except json.JSONDecodeError:
            return {"text": response.text}